<?php

namespace App\Library;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class WeChat{
    //微信api
    private $apis = [
        "host"      => 'https://mp.weixin.qq.com',
        "login"     => 'https://mp.weixin.qq.com/cgi-bin/bizlogin?action=startlogin',
        "captcha"   => 'https://mp.weixin.qq.com/cgi-bin/verifycode?username=',
        "qrcode"    => 'https://mp.weixin.qq.com/cgi-bin/loginqrcode?param=4300&action=getqrcode&rd=655',
        "loginask"  => 'https://mp.weixin.qq.com/cgi-bin/loginqrcode?action=ask&token=&lang=zh_CN&f=json&ajax=1&random=',
        "loginauth" => 'https://mp.weixin.qq.com/cgi-bin/loginauth?action=ask&token=&lang=zh_CN&f=json&ajax=1',
        "bizlogin"  => 'https://mp.weixin.qq.com/cgi-bin/bizlogin?action=login&lang=zh_CN'
    ];
    private $account = "";//账号
    private $cookieFile = "";//cookie文件

    public function __construct($account){
        $this->account = $account;
        $this->cookieFile = storage_path('cookie/cookies_'.$account.'.txt');
    }

    /**
     * 获取token和cookie
     * @return array
     */
    public function getToken(){
        $options = [
            'post' => [
                "lang"  => "zh_CN",
                "f"     => "json",
                "ajax"  => 1,
                "random"=> $this->getWxRandomNum(),
                "token" => ""
            ],
            'refer'=> $this->getRefer(),
        ];
        $result = $this->fetchCookies($this->apis['bizlogin'], $options);
        $response = $result['body'];
        $msg = $this->checkResponse($response);
        if ($msg !== true) {
            return $this->returnArr(false,$msg);
        }
        $cookies = $result['cookies'];
        //这是成功跳转的地址，从这上面获取token
        $redirect = $response["redirect_url"];
        if (preg_match('/token=([\d]+)/i', $redirect, $match)) {
            unlink($this->cookieFile);
            //保存数据库
            DB::table('wechat')->where('account',$this->account)->update([
                'token' => $match[1],
                'cookies' => json_encode($cookies),
            ]);
            return $this->returnArr(true,'成功',['token' => $match[1], 'cookies' => $cookies]);
        }
    }

    /**
     * 获取微信登陆二维码
     * @return array
     */
    public function getScan(){
        //第一次curl
        $this->fetch($this->apis['host'], "", "text");
        $info = DB::table('wechat')
            ->where('account',$this->account)
            ->first();
        if (empty($info)) {
            return $this->returnArr(false,'数据不存在，请刷新后重试。');
        }
        //第二次curl
        $options = [
            'refer' => $this->apis['host'],
            'post'  => [
                'username'  => $info->account,
                'pwd'       => md5($info->password),
                'f'         => 'json',
                'imgcode'   => '',
                'cookiefile'=> $this->cookieFile,
            ]
        ];
        $result = $this->fetch($this->apis['login'], $options);
//        if ($result['base_resp']['ret'] == '200008') {
//            //需要验证码，暂时留着
//            return $captchaInfo;
//        }
        $msg = $this->checkResponse($result);
        if ($msg !== true) {
            return $this->returnArr(false,$msg);
        }
        //第三次curl
        $options = ['refer' => $this->getRefer()];
        $qrcode = $this->fetch($this->apis['qrcode'], $options, "text");
        $qrcode = base64_encode($qrcode);
        //第四次curl
        $options = ['refer' => $this->apis['login']];
        $_result= $this->fetch($this->getRefer(), $options, "text");
        $matches = [];
        if (preg_match('/bindalias\:\s*\"(.*?)\"/is', $_result, $matches)) {
            return $this->returnArr(true,'成功',['manager' => $matches[1],'qrcode' => "data:png;base64," . $qrcode]);
        }



    }

    /**
     * 返回结果
     * @param bool $success
     * @param string $msg
     * @param array $other
     * @return array
     */
    private function returnArr($success = false,$msg = '', $other = []){
        return ['success' => $success, 'msg' => $msg,'other'=>$other];
    }


    /**
     * 检测二维码扫描状况
     * @return array
     */
    public function checkScan(){
        $link = $this->apis["loginask"];
        $options = ['refer' => $this->getRefer()];
        //二维码扫描状况curl
        $result = $this->fetch($link . $this->getWxRandomNum(), $options);
        $res = $this->checkResponse($result);
        if ($res !== true) {
            return $this->returnArr(false,$res);
        }
        switch ($result['status']){
            case 0:
                $msg = '请使用微信扫码';
                break;
            case 1:
                $msg = '已确认成功';
                break;
            case 2:
                $msg = empty($res['result']) ? '你已取消此次操作' : '扫码失败';//这里有点小问题，$res['result']压根没有
                break;
            case 3:
                $msg = '二维码已过期';
                break;
            case 4:
                $msg = '扫描成功,在手机上进行确认';
                break;
            default:
                $msg = '';
                break;
        }
        return $this->returnArr(true,$msg,['status'=>$result['status']]);
    }

    /**
     * 随机数
     * @return string
     */
    private function getWxRandomNum() {
        return "0." . mt_rand(1000000000000000, 9999999999999999);
    }

    /**
     * 获取跳转链接
     * @return string
     */
    private function getRefer() {
        return 'https://mp.weixin.qq.com/cgi-bin/bizlogin?action=validate&lang=zh_CN&account=' . $this->account;
    }

    /**
     * 解析crul结果
     * @param $data
     * @return bool|string
     */
    private function checkResponse($data) {
        if ($data['base_resp']['ret'] == 0){
            return true;
        }
        switch ($data['base_resp']['ret']) {
            case 200008:
                return "请输入图中的验证码。";
                break;
            case 200023:
                return "帐号或密码错误!";
                break;
            case -1:
                return "系统错误，请稍候再试。";
                break;
            case 200007:
                return "您目前处于访问受限状态。";
                break;
            case 200021:
                return "不存在该帐户。";
                break;
            case 200025:
                return "海外帐号请在公众平台海外版登录";
                break;
            case 200026:
                return "该公众会议号已经过期，无法再登录使用。";
                break;
            case 200027:
                return "您输入的验证码不正确，请重新输入。";
                break;
            case 200121:
                return "该帐号属于微信开放平台";
                break;
            case 200002:
                return "参数错误，请核对参数后重试。";
                break;
            case 200003:
                return "登录超时，请重新登录。";
                break;
            case 200004:
                return "请求页面的域名没有授权。";
                break;
            case 200005:
                return "请求方式错误，请确认请求方式后重试。";
                break;
            case 200006:
                return "表单名称验证出错，请核对表单名称后重试。";
                break;
            case 200007:
                return "对不起，你没有权限访问目标请求。";
                break;
            case 200040:
                return "登录超时，请重新登录。";
                break;
            default :
                return "未知的返回。";
                break;
        }
    }

    /**
     * curl 请求
     * @param $url
     * @param null $options
     * @param string $type
     * @return mixed
     */
    private function fetch($url, $options = null, $type = 'json') {
        $ch = curl_init();
        $useragent = $options['useragent'] ?? 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2';
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_AUTOREFERER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_POST, isset($options['post']));
        if (isset($options['post'])){
            curl_setopt($ch, CURLOPT_POSTFIELDS, $options['post']);
        }
        if (isset($options['refer'])){
            curl_setopt($ch, CURLOPT_REFERER, $options['refer']);
        }
        curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, ($options['timeout'] ?? 5));
        curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookieFile);
        curl_setopt($ch, CURLOPT_COOKIEFILE,$this->cookieFile);
        $result = curl_exec($ch);
        curl_close($ch);
        if ($type == 'json') {
            $result = json_decode($result, true);
        }
        return $result;
    }

    /**
     * curl 请求cookie
     * @param $url
     * @param null $options
     * @return array
     */
    private function fetchCookies($url, $options = null) {
        $ch = curl_init();
        $useragent = $options['useragent'] ?? 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2';
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_AUTOREFERER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_POST, isset($options['post']));
        if (isset($options['post'])){
            curl_setopt($ch, CURLOPT_POSTFIELDS, $options['post']);
        }
        if (isset($options['refer'])){
            curl_setopt($ch, CURLOPT_REFERER, $options['refer']);
        }
        curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, ($options['timeout'] ?? 5));
        curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookieFile);
        curl_setopt($ch, CURLOPT_COOKIEFILE,$this->cookieFile);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        $content = curl_exec($ch);
        curl_close($ch);
        list($header, $body) = explode("\r\n\r\n", $content);
        preg_match_all("/set\-cookie:([^\r\n]*)/is", $header, $matches);
        $cookie = $matches[1];
        return ['body' => json_decode($body, true), 'cookies' => $cookie];
    }


}